﻿using System.ComponentModel.DataAnnotations.Schema;
using Core.Common.Security;
using Core.Domain.Contracts;
using Core.Domain.Enums;
using Core.Domain.ValueObjects;
using Core.Helpers;

namespace Core.Domain.Entities;

/// <summary>
/// 用户表
/// </summary>
[Table("Users")]
public class User : AuditableEntity, IAggregateRoot
{
    // 构造函数私有化，强制使用工厂方法创建
    private User() { }

    // 关键业务字段（只读或内部可修改）
    public virtual string? Username { get; private set; } = null!;
    public virtual string? NormalizedUserName { get; private set; } = null!;
    public virtual string? Nickname { get; private set; }
    public virtual Avatar? Avatar { get; private set; }
    public virtual string? Email { get; private set; }
    public virtual string? NormalizedEmail { get; private set; }
    public virtual bool? EmailConfirmed { get; private set; }
    public virtual string? PasswordHash { get; private set; }
    public virtual string? SecurityStamp { get; private set; } = Guid.CreateVersion7().ToString();
    public virtual string? ConcurrencyStamp { get; private set; } = Guid.CreateVersion7().ToString();
    public virtual PhoneNumber? PhoneNumber { get; private set; }
    public virtual bool? PhoneNumberConfirmed { get; private set; }
    public virtual bool? TwoFactorEnabled { get; private set; }
    public virtual UserLockout? Lockout { get; private set; } = UserLockout.NotLocked();
    public virtual GenderType? Gender { get; private set; } = GenderType.Secrecy;
    public virtual string? Signature { get; private set; }
    /// <summary>
    /// 是否是超级管理员/免权限校验用户
    /// </summary>
    public virtual bool? IsSuperAdmin { get; private set; } = false;
    // 导航属性（聚合内部）
    private readonly List<UserRole> _roles = new();
    public virtual IReadOnlyCollection<UserRole>? UserRoles => _roles?.AsReadOnly();

    private readonly List<UserOrganization> _userOrganizations = new();
    public virtual IReadOnlyCollection<UserOrganization>? UserOrganizations => _userOrganizations?.AsReadOnly();

    public User(string username, string password, string? email)
    {
        ExceptionHelper.ThrowIfNullOrWhiteSpace(username, "用户名不能为空");

        Username = username.Trim();
        NormalizedUserName = username.ToUpperInvariant();
        Email = email;
        NormalizedEmail = email?.ToUpperInvariant();

        SetPassword(password);
        ChangeNickname(username);
    }

    public static User Register(string username, string password, string? email)
    {
        return new User(username, password, email);
    }

    public static User Create(string username, string password, string? email)
    {
        return new User(username, password, email);
    }

    public void Update(string nickname, string email, string phoneNumber, string avatar)
    {
        Email = email;
        NormalizedEmail = email?.ToUpperInvariant();

        ChangeNickname(nickname);
        SetPhoneNumber(phoneNumber);
        ChangeAvatar(avatar, "image/png");
    }

    // 行为：设置密码（封装业务规则）
    public void SetPassword(string password)
    {
        ExceptionHelper.ThrowIfTrue(password.Length < 6, "密码长度不能少于6位");

        PasswordHash = password.HashPassword();
        SecurityStamp = Guid.CreateVersion7().ToString();
    }

    // 行为：验证密码
    public bool VerifyPassword(string password)
    {
        return !string.IsNullOrEmpty(PasswordHash) &&
               password.VerifyPassword(PasswordHash);
    }

    //  行为：确认邮箱
    public void ConfirmEmail()
    {
        EmailConfirmed = true;
    }

    // 行为：设置手机号（使用值对象）
    public void SetPhoneNumber(string number, bool confirmed = false)
    {
        PhoneNumber = new PhoneNumber(number);
        PhoneNumberConfirmed = confirmed;
    }

    /// <summary>
    /// 设置性别
    /// </summary>
    /// <param name="gender"></param>
    public void SetGender(GenderType gender)
    {
        Gender = gender;
    }

    /// <summary>
    /// 设置账号状态
    /// </summary>
    /// <param name="enabled"></param>
    public void SetEnabled(bool enabled)
    {
        if (Enabled == enabled) return;
        Enabled = enabled;
    }

    /// <summary>
    /// 设置备注
    /// </summary>
    /// <param name="description"></param>
    public void SetDescription(string? description)
    {
        if (Description == description) return;
        Description = description;
    }

    /// <summary>
    /// 设置签名
    /// </summary>
    /// <param name="sign"></param>
    public void SetSignature(string sign)
    {
        if (Signature == sign) return;
        Signature = sign;
    }

    // 行为：启用双因子认证
    public void EnableTwoFactorAuth()
    {
        TwoFactorEnabled = true;
    }

    // 行为：锁定用户
    public void LockUntil(DateTimeOffset lockoutEnd)
    {
        Lockout = UserLockout.LockedUntil(lockoutEnd);
    }

    // 行为：解锁用户
    public void Unlock()
    {
        Lockout = UserLockout.NotLocked();
    }

    // 行为：登录失败计数
    public void RecordLoginFailure()
    {
        Lockout = Lockout?.IncrementFailure();
    }

    /// <summary>
    /// 修改头像
    /// </summary>
    /// <param name="ossUrl"></param>
    /// <param name="contentType"></param>
    public void ChangeAvatar(string ossUrl, string contentType)
    {
        Avatar = new Avatar(ossUrl, contentType);
    }

    /// <summary>
    /// 修改昵称
    /// </summary>
    /// <param name="nickname"></param>
    /// <exception cref="ArgumentException"></exception>
    public void ChangeNickname(string nickname)
    {
        ExceptionHelper.ThrowIfNullOrWhiteSpace(nickname, "昵称不能为空");

        Nickname = nickname.Trim();
    }

    public async Task<bool> CheckPasswordAsync(User user, string password)
    {
        return await Task.FromResult(user.VerifyPassword(password));
    }

    public override string? ToString() => Username;

    public void SetEmail(string email)
    {
        if (Email == email) return;
        Email = email;
        NormalizedEmail = email?.ToUpperInvariant();
    }

    public void ClearRoles()
    {
        if (_roles.Any())
            _roles.Clear();
    }

    public void AssignRole(Guid roleId)
    {
        if (_roles.Any(r => r.RoleId == roleId))
            return;

        _roles.Add(UserRole.Create(Id, roleId));
    }

    public void SetSuperAdmin(bool isSuperAdmin)
    {
        IsSuperAdmin = isSuperAdmin;
    }
}
